#include "testApp.h"
#include "stdio.h"

//--------------------------------------------------------------
testApp::testApp(){
}

//--------------------------------------------------------------
void testApp::setup() {
//	srand((unsigned int)time((time_t *)NULL));
	
	// 0 output channels, 
	// 2 input channels
	// 44100 samples per second
	// BUFFER_SIZE samples per buffer
	// 4 num buffers (latency)
	
	ofSoundStreamSetup(0,2,this, 44100,BUFFER_SIZE, 4);	
	left = new float[BUFFER_SIZE];
	right = new float[BUFFER_SIZE];

	for (int i = 0; i < NUM_WINDOWS; i++)
	{
		for (int j = 0; j < BUFFER_SIZE/2; j++)
		{
			freq[i][j] = 0;	
		}
	}
	
	// listen on the given port
	cout << "listening for osc messages on port " << PORT << "\n";
	receiver.setup( PORT );

	ofSetFrameRate(120);
	ofSetFullscreen(true);

	camWidth 		= 1024;	// try to grab at this size. 
	camHeight 		= 800;
	
//	vidGrabber.setVerbose(true);
//	vidGrabber.initGrabber(camWidth,camHeight);
	
	ofSetVerticalSync(true);
	ofBackground(0, 0, 0);
	ofSetLogLevel(OF_LOG_NOTICE);
	size = 25;	
	user = 0;
	allUsers = false;
	camOn = true;
	audioinc = 0;

	time_old = ofGetElapsedTimeMillis();

	for(int i=0; i<MAXUSERS; i++)
	{
			time[i] = 0;
			tot_magnitude[i] = 0.0;
			volume_amo[i] = 0.0;
	}

	global_mode = MODE_RODA;
}

//--------------------------------------------------------------
void testApp::update() {
	
//	vidGrabber.grabFrame();

	// check for waiting messages
	while( receiver.hasWaitingMessages() )
	{
		// get the next message
		ofxOscMessage m;
		receiver.getNextMessage( &m );

		// check for mouse moved message
		if ( m.getAddress() == "user" )
		{
			global_mode = MODE_RODA;

		    int OSCparam = m.getArgAsInt32( 0 );
		    string OSCparam1 = m.getArgAsString( 1 );
		    int OSCparam2 = m.getArgAsInt32( 2 );
		    if (OSCparam==0)
		    {
//                if (OSCparam1 == "play" && OSCparam2==1)
//                    Nplayer = 0;
                if (OSCparam1 == "size")
                    Turnsize = OSCparam2;
		    }
		    if (OSCparam==1)
		    {
                if (OSCparam1 == "play" && OSCparam2==1)
                    user = 0;
					count[0]=CTIME;
		    }
		    if (OSCparam==2)
		    {
                if (OSCparam1 == "play" && OSCparam2==1)
                    user = 1;
					count[1]=CTIME;
		    }
		    if (OSCparam==3)
		    {
                if (OSCparam1 == "play" && OSCparam2==1)
                    user = 2;
					count[2]=CTIME;
		    }
		    if (OSCparam==4)
		    {
                if (OSCparam1 == "play" && OSCparam2==1)
                    user = 3;
					count[3]=CTIME;
		    }
		    if (OSCparam==5)
		    {
                if (OSCparam1 == "play" && OSCparam2==1)
                    user = 4;
					count[4]=CTIME;
		    }
		    if (OSCparam==6)
		    {
                if (OSCparam1 == "play" && OSCparam2==1)
                    user = 5;
					count[5]=CTIME;
		    }
		    if (OSCparam==7)
		    {
                if (OSCparam1 == "play" && OSCparam2==1)
                    user = 6;
					count[6]=CTIME;
		    }
		    if (OSCparam==8)
		    {
                if (OSCparam1 == "play" && OSCparam2==1)
                    user = 7;
					count[7]=CTIME;
		    }
		}
	
		// check for mouse moved message
		if ( m.getAddress() == "/test"  && m.getNumArgs() == 9)
		{
			cout << "/test";
			global_mode = MODE_SOLITUDE;

		    int OSCparam = m.getArgAsInt32( 0 );
			cout << " " << OSCparam << " ";
		    int OSCx1 = m.getArgAsInt32( 1 );
			cout << OSCx1 << " ";
		    int OSCy1 = m.getArgAsInt32( 2 );
			cout << OSCy1 << " ";
		    int OSCw1 = m.getArgAsInt32( 3 );
			cout << OSCw1 << " ";
		    int OSCa1 = m.getArgAsInt32( 4 );
			cout << OSCa1 << " ";
		    int OSCx2 = m.getArgAsInt32( 5 );
			cout << OSCx2 << " ";
		    int OSCy2 = m.getArgAsInt32( 6 );
			cout << OSCy2 << " ";
		    int OSCw2 = m.getArgAsInt32( 7 );
			cout << OSCw2 << " ";
		    int OSCa2 = m.getArgAsInt32( 8 );
			cout << OSCa2 << " ";

			time[OSCparam] = (OSCx2-OSCx1) * T_TIME / 100.0;
			tot_magnitude[OSCparam] = 255*OSCa1/100.0;
			volume_amo[OSCparam] = (float)(255.0*(OSCa2 - OSCa1) / (float)(time[OSCparam]*100.0));
			cout << "t:" << tot_magnitude[OSCparam] << endl;

		}
			
	}

	if( global_mode == MODE_SOLITUDE)
	{
		int time_now = ofGetElapsedTimeMillis();
		time_amo = time_now - time_old;

		for(int i=0; i<MAXUSERS; i++)
		{
			if(time[i] > 0)
			{
				tot_magnitude[i] = tot_magnitude[i] + (volume_amo[i]*time_amo);
				cout << i << "->" << tot_magnitude[i] << endl;
				time[i] = time[i] - time_amo;
			}
		}

		time_old = time_now;
	}
}

//--------------------------------------------------------------
void testApp::draw() {
	static int index=0;
	float avg_power = 0.0f;	
	
	if(global_mode == MODE_RODA)
	{
		if(index < NUM_WINDOWS)
			index += 1;
		else
			index = 0;
		
		/* do the FFT	*/
		myfft.powerSpectrum(0,(int)BUFFER_SIZE/2, left,BUFFER_SIZE,&magnitude[0],&phase[0],&power[0],&avg_power);
	
		/* start from 1 because mag[0] = DC component */
		/* and discard the upper half of the buffer */
		for(int j=1; j < BUFFER_SIZE/2; j++) {
			freq[index][j] = magnitude[j];		
		}

		tot_magnitude[user] = 0;
		for (int i = 1; i < (int)(BUFFER_SIZE/2); i++){
			tot_magnitude[user] = tot_magnitude[user] + magnitude[i];
		}
		tot_magnitude[user] = pow(tot_magnitude[user],3) + audioinc;
		if (tot_magnitude[user] > 255.)
			tot_magnitude[user] = 255.;

		if(allUsers)
		{
			for(int j=0; j<MAXUSERS; j++)
				tot_magnitude[j] = 255.;
		}

		ofSetColor(255, 255, 255);


		ofEnableAlphaBlending();
		ofFill();


		for(int j=0; j<MAXUSERS; j++){

			if (user == j || allUsers || Turnsize < 80)
			{
				choosecolor(j);
				for(int i=0; i<boles[j].size(); i++) {
					ofCircle(boles[j][i].pt.x, boles[j][i].pt.y, boles[j][i].size);	
				}
			}
			if (user != j && tot_magnitude[j]>0)
			{
				choosecolor(j);
				for(int i=0; i<boles[j].size(); i++) {
					ofCircle(boles[j][i].pt.x, boles[j][i].pt.y, boles[j][i].size);	
				}
				tot_magnitude[j]=tot_magnitude[j]-CTIME;
				if(tot_magnitude[j] < 0.)
					tot_magnitude[j] = 0.;
			}
		}
		ofDisableAlphaBlending();

		px = mouseX;
		py = mouseY;
	
		if (allUsers)
			ofCircle(50, 50, size);	

	}
	else
	{
		ofEnableAlphaBlending();
		ofFill();
		for(int j=0; j<MAXUSERS; j++){

			if (time[j]>0)
			{
				choosecolor(j);
				for(int i=0; i<boles[j].size(); i++) {
					ofCircle(boles[j][i].pt.x, boles[j][i].pt.y, boles[j][i].size);	
				}
			}
		}
		ofDisableAlphaBlending();
	}

}

//--------------------------------------------------------------
void testApp::keyPressed(int key) {
	if (key == '1')
	{
		user = 0;
		count[0]=CTIME;
	}
	if (key == '2') 
	{
		user = 1;
		count[1]=CTIME;
	}
	if (key == '3') 
	{
		user = 2;
		count[2]=CTIME;
	}
	if (key == '4') 
	{
		user = 3;
		count[3]=CTIME;
	}
	if (key == '5') 
	{
		user = 4;
		count[4]=CTIME;
	}
	if (key == '6') 
	{
		user = 5;
		count[5]=CTIME;
	}
	if (key == '7') 
	{
		user = 6;
		count[6]=CTIME;
	}
	if (key == '8') 
	{
		user = 7;
		count[7]=CTIME;
	}
	if (key == 'c') 
		camOn = !camOn;
	if (key == 'x') 
		boles[user].clear();
	if (key == 'z') 
		if (boles[user].size() > 0)
			boles[user].erase(boles[user].end()-1);
	if (key == 'a') 
		allUsers = !allUsers;
	if(key == OF_KEY_UP) 
		size++;
	if(key == OF_KEY_DOWN) 
		size--;
	if(key == OF_KEY_LEFT) 
		audioinc--;
	if(key == OF_KEY_RIGHT) 
		audioinc++;


}

//--------------------------------------------------------------
void testApp::keyReleased(int key) {
}

//--------------------------------------------------------------
void testApp::mouseMoved(int x, int y ) {
	
}

//--------------------------------------------------------------
void testApp::mouseDragged(int x, int y, int button) {
	
	bola bola_tmp;
	bola_tmp.size = size;
	bola_tmp.pt.x = mouseX;
	bola_tmp.pt.y = mouseY;
	boles[user].push_back(bola_tmp);
}

//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button) {
	
	
}

//--------------------------------------------------------------
void testApp::mouseReleased(int x, int y, int button){
	
}

//--------------------------------------------------------------
void testApp::resized(int w, int h){
	
}

void testApp::choosecolor(int j){

	switch(j+1){
		case 1:// pink
			ofSetColor(228, 0, 128, tot_magnitude[j]);
			break;
		case 2: // yellow
			ofSetColor(228, 228, 0,  tot_magnitude[j]);
			break;
		case 3: // magenta
			ofSetColor(255,0 , 255,  tot_magnitude[j]);
			break;
		case 4: // cian
			ofSetColor(0, 228, 228,  tot_magnitude[j]);
			break;
		case 5: // red
			ofSetColor(255, 0, 0,  tot_magnitude[j]);
			break;
		case 6: // green
			ofSetColor(0, 228, 0,  tot_magnitude[j]);
			break;
		case 7: // blue
			ofSetColor(0, 0, 228,  tot_magnitude[j]);
			break;
		case 8: //gray
			ofSetColor(128, 128, 128,  tot_magnitude[j]);
			break;
	}
}

//--------------------------------------------------------------
void testApp::audioReceived 	(float * input, int bufferSize, int nChannels){	
	// samples are "interleaved"
	for (int i = 0; i < bufferSize; i++){
		left[i] = input[i*2];
		right[i] = input[i*2+1];
	}
	bufferCounter++;
}

